﻿using Microsoft.AspNetCore.Razor.TagHelpers;
using System.Diagnostics;
using System.Text.RegularExpressions;
using System.Text;
using CemsTransfer.Models;

namespace CemsTransfer.BUS
{
    public class NetWorkBUS
    {
        public void RunCommand(string command)
        {
            Process.Start("sudo", command);
        }

        public List<NetInfo> GetNetInfo(int networknum)
        {
            List<NetInfo> NetInfos = new List<NetInfo>();
            try
            {
                StreamReader reader = new StreamReader(@"/etc/netplan/01-network-manager-all.yaml", Encoding.Default);
                string theReply = reader.ReadToEnd();
                reader.Close();
                for (int k = 1; k < networknum + 1; k++)
                {
                    NetInfo line18NetInfo = new NetInfo();
                    line18NetInfo.ID = k;
                    Regex strRegex = new Regex(string.Format(@"(?<str>([^\w\s]+|\s*)enp{0}s0:\s*dhcp4: no([\w\W]*))", k));
                    Regex addressRegex = new Regex(@"([^\w\s]+|\s*)addresses:\s*[^\w\s](?<address>\d+.\d+.\d+.\d+/\d+)]\s*");
                    Regex gatewayRegex = new Regex(@"([^\w\s]+|\s*)gateway4:\s*(?<gateway>\d+.\d+.\d+.\d+)\s*");
                    Regex maskReg = new Regex(@"\d+.\d+.\d+.\d+/(?<mask>\d+)\s*");
                    Regex ipRegex = new Regex(@"\s*(?<ip>\d+.\d+.\d+.\d+)\s*");
                    Regex routesRegex = new Regex(@"(?<routes>([^\w\s]+|\s*)routes:([\w\W]*))");
                    Regex routes_addressRegex = new Regex(@"([^\w\s]+|\s*)-\s*to:\s*(?<routeaddress>\d+.\d+.\d+.\d+/\d+)\s*");
                    Regex routes_gatewayRegex = new Regex(@"([^\w\s]+|\s*)via:\s*(?<via>\d+.\d+.\d+.\d+)\s*");
                    MatchCollection strCollection = strRegex.Matches(theReply);

                    if (strCollection.Count > 0)
                    {
                        string str_value = strCollection[0].Groups["str"].Value;
                        MatchCollection addressCollection = addressRegex.Matches(str_value);
                        MatchCollection gatewayCollection = gatewayRegex.Matches(str_value);
                        MatchCollection routesCollection = routesRegex.Matches(str_value);
                        if (addressCollection.Count > 0)
                        {
                            string str = addressCollection[0].Groups["address"].Value.Trim();
                            string ip = ipRegex.Matches(str)[0].Groups["ip"].Value.Trim();
                            line18NetInfo.IP = ip;
                            int mask = Convert.ToInt32(maskReg.Matches(str)[0].Groups["mask"].Value.Trim());
                            string Mask = GetMask(mask);
                            line18NetInfo.Mask = Mask;

                            if (gatewayCollection.Count > 0)
                            {
                                string str_4 = gatewayCollection[0].Groups["gateway"].Value.Trim();
                                string ip_4 = ipRegex.Matches(str_4)[0].Groups["ip"].Value.Trim();
                                line18NetInfo.GateWay = ip_4;
                            }
                            else
                            {
                                line18NetInfo.GateWay = "";
                            }

                            MatchCollection routesstrCollection = routesRegex.Matches(str_value);
                            if (routesstrCollection.Count > 0)
                            {
                                string routestr_value = routesstrCollection[0].Groups["routes"].Value;
                                MatchCollection route_addressCollection = routes_addressRegex.Matches(routestr_value);
                                MatchCollection route_gatewayCollection = routes_gatewayRegex.Matches(routestr_value);

                                if (route_addressCollection.Count > 0)
                                {
                                    string str_3 = route_addressCollection[0].Groups["routeaddress"].Value.Trim();
                                    string ip_3 = ipRegex.Matches(str_3)[0].Groups["ip"].Value.Trim();
                                    line18NetInfo.RouteIP = ip_3;
                                    int mask_3 = Convert.ToInt32(maskReg.Matches(str)[0].Groups["mask"].Value.Trim());
                                    string Mask_3 = GetMask(mask);
                                    line18NetInfo.RouteMask = Mask_3;
                                }
                                else
                                {
                                    line18NetInfo.RouteIP = "";
                                    line18NetInfo.RouteMask = "";
                                }

                                if (route_gatewayCollection.Count > 0)
                                {
                                    string str_2 = route_gatewayCollection[0].Groups["via"].Value.Trim();
                                    string ip_2 = ipRegex.Matches(str_2)[0].Groups["ip"].Value.Trim();
                                    line18NetInfo.RouteGateWay = ip_2;
                                }
                                else
                                {
                                    line18NetInfo.RouteGateWay = "";
                                }
                            }
                        }
                        else
                        {
                            line18NetInfo.IP = "";
                            line18NetInfo.Mask = "";
                        }
                    }
                    NetInfos.Add(line18NetInfo);
                }
                return NetInfos;
            }
            catch (Exception ex)
            {
                return NetInfos;
            }
        }

        public string GetMask(int value)
        {
            try
            {
                string str = string.Empty;
                for (int i = 0; i < value; i++)
                {
                    str += "1";
                }
                str = str.PadRight(32, '0');
                string a = Convert.ToInt32(str.Substring(0, 8), 2).ToString() + "." + Convert.ToInt32(str.Substring(8, 8), 2).ToString() + "." + Convert.ToInt32(str.Substring(16, 8), 2).ToString() + "." + Convert.ToInt32(str.Substring(24, 8), 2).ToString();
                return a;
            }
            catch
            {
                return "0.0.0.0";
            }
        }

        public bool UpdateLine18NetInfo(NetInfo netInfo, int networknum)
        {
            try
            {
                List<NetInfo> line18NetInfos = new List<NetInfo>();
                line18NetInfos = GetNetInfo(networknum);

                RunCommand("chmod 777 /etc/netplan/01-network-manager-all.yaml");
                using (FileStream fileStream = new FileStream("/etc/netplan/01-network-manager-all.yaml", FileMode.Open, FileAccess.Write, FileShare.Write))
                {
                    fileStream.Seek(0, SeekOrigin.Begin);
                    fileStream.SetLength(0);
                    using (StreamWriter streamWriter = new StreamWriter(fileStream))
                    {
                        streamWriter.WriteLine("network:");
                        streamWriter.WriteLine("  version: 2");
                        streamWriter.WriteLine("  renderer: NetworkManager");
                        streamWriter.WriteLine("  ethernets:");
                        foreach (var item in line18NetInfos)
                        {
                            if (item.ID == netInfo.ID)
                            {
                                streamWriter.WriteLine("    enp" + netInfo.ID + "s0:");
                                streamWriter.WriteLine("      dhcp4: no");
                                streamWriter.WriteLine("      addresses: [" + netInfo.IP + "/" + MaskToInt(netInfo.Mask) + "]");
                                streamWriter.WriteLine("      gateway4: " + netInfo.GateWay);
                            }
                            else
                            {
                                if (string.IsNullOrEmpty(item.IP))
                                {
                                    streamWriter.WriteLine("    enp" + item.ID + "s0:");
                                    streamWriter.WriteLine("      dhcp4: yes");
                                }
                                else
                                {
                                    streamWriter.WriteLine("    enp" + item.ID + "s0:");
                                    streamWriter.WriteLine("      dhcp4: no");
                                    streamWriter.WriteLine("      addresses: [" + item.IP + "/" + MaskToInt(item.Mask) + "]");
                                    streamWriter.WriteLine("      gateway4: " + item.GateWay);
                                }
                            }
                        }

                        fileStream.Flush();
                        streamWriter.Close();
                    }

                    fileStream.Close();
                }
                RunCommand("netplan apply");
                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
        }

        public string MaskToInt(string mask)
        {
            string value = string.Empty;
            string[] array = mask.Replace(" ", "").Split('.');
            for (int i = 0; i < array.Length; i++)
            {
                value += Convert.ToString(Convert.ToInt32(array[i]), 2);
            }
            value = value.PadRight(32, '0');

            string keyWord = "1";
            int index = 0;
            int count = 0;
            while ((index = value.IndexOf(keyWord, index)) != -1)
            {
                count++;
                index = index + keyWord.Length;
            }
            return count.ToString();
        }
    }
}
